"""
The ``open`` command is a very important command in the Papis workflow.
With it you can open documents, folders or marks.

Marks
^^^^^

One of this command's special features is the ability to use marks for
documents. For instance, if our library consists of PDF files and EPUB
files, we would like to define bookmarks in order to go back to them at some
later point.

How you define marks can be customized through the marks configuration
settings :ref:`here <marks-options>`. The default way of doing it is just by
defining a ``marks`` list in a document. Let us look at a concrete example:

.. code:: yaml

    author: Isaiah Shavitt, Rodney J. Bartlett
    edition: '1'
    files: [book.pdf]
    isbn: 052181832X,9780521818322

    marks:
    - {name: Intermediates definition, value: 344}
    - {name: EOM equations, value: 455}

    publisher: Cambridge University Press
    ref: book:293288
    series: Cambridge Molecular Science
    title: 'Many-Body Methods in Chemistry and Physics'
    type: book
    year: '2009'

This book has two defined marks. Each mark has a name and a value. If you tell
the ``open`` command to open marks, it will look for the marks and open the
value (page number). This is the default behavior. However, if you go to the
:ref:`configuration <marks-options>`, you'll see that you can change the
convention to what suits you.

Examples
^^^^^^^^

- Open a PDF file linked to a document matching the string ``bohm``:

    .. code:: sh

        papis open bohm

- Open the folder where this last document is stored:

    .. code:: sh

        papis open -d bohm

  The file browser used is given by the :confval:`file-browser` setting.

- Open a mark defined in the info file:

    .. code:: sh

        papis open --mark bohm

Command-line interface
^^^^^^^^^^^^^^^^^^^^^^

.. click:: papis.commands.open:cli
    :prog: papis open
"""
from __future__ import annotations

import os
from typing import TYPE_CHECKING

import click

import papis.cli
import papis.config
import papis.logging

if TYPE_CHECKING:
    from papis.document import Document

logger = papis.logging.get_logger(__name__)


def run(document: Document,
        opener: str | None = None,
        folder: bool = False,
        mark: bool = False) -> None:
    if opener is not None:
        papis.config.set("opentool", papis.config.escape_interp(opener))

    from papis.document import describe, from_data

    doc_folder = document.get_main_folder()
    if doc_folder is None:
        from papis.exceptions import DocumentFolderNotFound
        raise DocumentFolderNotFound(describe(document))

    from papis.api import open_dir, open_file, pick
    from papis.format import format

    if folder:
        open_dir(doc_folder)
    else:
        if mark:
            logger.debug("Getting document's marks.")
            marks = document[papis.config.getstring("mark-key-name")]
            if marks:
                mark_fmt = papis.config.getformatpattern("mark-header-format")
                mark_name = papis.config.getstring("mark-format-name")
                mark_opener = papis.config.getstring("mark-opener-format")

                if not mark_fmt:
                    raise ValueError(
                        "No mark header format given. Set 'mark-header-format' in "
                        "the configuration file")

                if not mark_name:
                    raise ValueError(
                        "No mark name format given. Set 'mark-format-name' "
                        "in the configuration file")

                mark_dict = pick(
                    marks,
                    header_filter=lambda x: format(mark_fmt, x, doc_key=mark_name),
                    match_filter=lambda x: format(mark_fmt, x, doc_key=mark_name))

                if mark_dict:
                    if not mark_opener:
                        raise ValueError(
                            "No mark opener format given. Set 'mark-opener-format' "
                            "in the configuration file")

                    opener = format(
                        mark_opener,
                        from_data(mark_dict[0]),
                        doc_key=mark_name)

                    logger.info("Setting opener to '%s'.", opener)
                    papis.config.set("opentool", papis.config.escape_interp(opener))

        files = document.get_files()
        if not files:
            logger.error("The chosen document has no files attached: '%s'.",
                         describe(document))
            return

        files_to_open = pick(files, header_filter=os.path.basename)
        for file_to_open in files_to_open:
            open_file(file_to_open, wait=False)


@click.command("open")
@click.help_option("-h", "--help")
@papis.cli.query_argument()
@papis.cli.sort_option()
@papis.cli.doc_folder_option()
@papis.cli.all_option()
@click.option(
    "--tool",
    help="Tool for opening the file (opentool).",
    default="")
@papis.cli.bool_flag(
    "-d", "--dir", "folder",
    help="Open directory.")
@papis.cli.bool_flag(
    "-m", "--mark/--no-mark",
    help="Open mark.",
    default=lambda: papis.config.getboolean("open-mark"))
def cli(query: str, doc_folder: tuple[str, ...], tool: str, folder: bool,
        sort_field: str | None, sort_reverse: bool, _all: bool,
        mark: bool) -> None:
    """Open document from a given library."""
    if tool:
        papis.config.set("opentool", papis.config.escape_interp(tool))

    documents = papis.cli.handle_doc_folder_query_all_sort(query,
                                                           doc_folder,
                                                           sort_field,
                                                           sort_reverse,
                                                           _all)
    if not documents:
        from papis.strings import no_documents_retrieved_message
        logger.warning(no_documents_retrieved_message)
        return

    for document in documents:
        run(document, folder=folder, mark=mark)
